package org.pp.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.wechat.pay.java.core.RSAAutoCertificateConfig;
import com.wechat.pay.java.core.exception.ValidationException;
import com.wechat.pay.java.core.notification.NotificationParser;
import com.wechat.pay.java.core.notification.RequestParam;
import com.wechat.pay.java.service.payments.jsapi.JsapiServiceExtension;
import com.wechat.pay.java.service.payments.jsapi.model.*;
import com.wechat.pay.java.service.payments.model.Transaction;
import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.pp.config.WechatPayConfig;
import org.pp.core.*;
import org.pp.entity.PpOrder;
import org.pp.entity.PpUser;
import org.pp.miniapp.dto.RequestPay;
import org.pp.service.IPpOrderService;
import org.pp.service.IPpPayService;
import org.pp.service.IPpUserService;
import org.pp.vo.MiniappPrepayVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.ServletRequestUtils;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;

@Service
@Slf4j
public class PpPayServiceImpl implements IPpPayService {
    @Autowired
    IPpUserService userService;

    @Autowired
    IPpOrderService orderService;

    @Autowired
    RSAAutoCertificateConfig certificateConfig;

    @Autowired
    WechatPayConfig config;

    @Override
    public MiniappPrepayVo request(RequestPay pay) {
        Long userId = MiniappSessionUtil.getUserId();
        PpUser user = userService.getById(userId);
        Assertion.nullThrow(user,"下单失败");

        PpOrder order = orderService.getByOrderNo(pay.getOrderNo());
        Assertion.nullThrow(order,"订单不存在");

        if (!Constants.orderToPayStatus.equals(order.getStatus())){
            throw BizExcept.erro("订单状态异常");
        }

        if(Constants.channelMiniPay.equals(pay.getChannel())){
            JsapiServiceExtension service =
                    new JsapiServiceExtension.Builder().config(certificateConfig).build();

            PrepayRequest request = new PrepayRequest();
            Amount amount = new Amount();
            //金额，分
            amount.setTotal(order.getPayPrice().multiply(BigDecimal.valueOf(100)).intValue());
            request.setAmount(amount);
            request.setAppid(config.getAppid());
            request.setMchid(config.getMerchantId());
            request.setDescription("商品支付："+order.getNames());
            request.setNotifyUrl(config.getNotifyUrl());
            request.setOutTradeNo(order.getOrderNo());
            Payer payer = new Payer();
            payer.setOpenid(user.getOpenId());
            request.setPayer(payer);
            PrepayWithRequestPaymentResponse response = service.prepayWithRequestPayment(request);
            return BeanUtil.copyProperties(response,MiniappPrepayVo.class);
        }

        return null;
    }

    @Override
    public ResponseEntity<Object> callBack(String requestBody) {
        HttpServletRequest request = MiniappSessionUtil.getRequest();
        RequestParam requestParam = new RequestParam.Builder()
                .serialNumber(request.getHeader("Wechatpay-Serial"))
                .nonce(request.getHeader("Wechatpay-Nonce"))
                .signature(request.getHeader("Wechatpay-Signature"))
                .timestamp(request.getHeader("Wechatpay-Timestamp"))
                .signType(request.getHeader("Wechatpay-Signature-Type"))
                .body(requestBody)
                .build();

        NotificationParser parser = new NotificationParser(certificateConfig);
        try {
            // 以支付通知回调为例，验签、解密并转换成 Transaction
            Transaction transaction = parser.parse(requestParam, Transaction.class);
            if(Transaction.TradeStateEnum.SUCCESS.equals(transaction.getTradeState())){
                PpOrder order = orderService.getByOrderNo(transaction.getOutTradeNo());

                if(Objects.isNull(order)){
                    return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build();
                }
                if (!Constants.orderToPayStatus.equals(order.getStatus())){
                    //throw BizExcept.erro("订单状态异常");
                    return ResponseEntity.status(HttpStatus.OK).build();
                }
                PpOrder editeOrder= new PpOrder();
                editeOrder.setOrderId(order.getOrderId());
                editeOrder.setStatus(Constants.orderPayedStatus);
                editeOrder.setPayedTime(LocalDateTime.now());
                orderService.updateById(editeOrder);
                // 处理成功，返回 200 OK 状态码
                return ResponseEntity.status(HttpStatus.OK).build();
            }else{
                return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build();
            }
        } catch (ValidationException e) {
            // 签名验证失败，返回 401 UNAUTHORIZED 状态码
            log.error("sign verification failed", e);
            return ResponseEntity.status(HttpStatus.UNAUTHORIZED).build();
        }
    }

    @Override
    public void query(String orderNo) {
        PpOrder order = orderService.getByOrderNo(orderNo);
        Assertion.nullThrow(order,"订单不存在");

        if (!Constants.orderToPayStatus.equals(order.getStatus())){
            //throw BizExcept.erro("订单状态异常");
            return;
        }

        JsapiServiceExtension service =
                new JsapiServiceExtension.Builder().config(certificateConfig).build();
        QueryOrderByOutTradeNoRequest request= new QueryOrderByOutTradeNoRequest();
        request.setMchid(config.getMerchantId());
        request.setOutTradeNo(order.getOrderNo());
        Transaction transaction = service.queryOrderByOutTradeNo(request);
        if(Transaction.TradeStateEnum.SUCCESS.equals(transaction.getTradeState())){
            //
            PpOrder editeOrder= new PpOrder();
            editeOrder.setOrderId(order.getOrderId());
            editeOrder.setStatus(Constants.orderPayedStatus);
            editeOrder.setPayedTime(LocalDateTime.now());
            orderService.updateById(editeOrder);
        }else{
            log.info("查询结果::"+transaction.getTradeStateDesc());
        }
    }


}
